/*
 * main.cpp
 *
 *  Created on: 21.12.2008
 *      Author: felix
 */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef __APPLE__
#include <OpenGL/gl.h>  // The GL Header File
#include <GLUT/glut.h>  // The GL Utility Toolkit (Glut) Header
#else
#include <GL/gl.h>      // The GL Header File
#include <GL/glut.h>    // The GL Utility Toolkit (Glut) Header
#endif

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

struct Point{
	float x,y,z;
};

int width_ = 512;
int height_ = 512;
int fovy_ = 45;
int near_ = 50;
int far_ = 1000;
bool isAnaglyph = false;
float angle = 0;

double camPos[3] = {0.0, 50.0, -100.0};
GLfloat lightPos[4] = {0, 1.0, -300.0, 0.0};

//stereographie variables
double eyesep_ = 4.0;
Point position;
Point focus;
float top_ = 1000;
float bottom_ = 1000;
float left_ = 1000;
float right_ = 1000;

void drawGeometry() {
//
	glClear(GL_DEPTH_BUFFER_BIT);
	glRotatef(angle, 0, 1, 0);
//	glColor4f(1, 1, 0, 1);
//	glBegin(GL_QUADS);
//		glVertex3f(30, -30, 0);
//		glVertex3f(30, 30, 0);
//		glVertex3f(-30, 30, 0);
//		glVertex3f(-30, -30, 0);
//	glEnd();
	glutSolidCube(40);
}

void setFrustum(bool isLeftEye) {

	double b,t;
	t = near_ * tan(fovy_ * M_PI / 360.0);
	b = -t;

	//focallength kann so berechnet werden, weil unser focus immer im nullpunkt liegt
	double c = sqrt(position.x*position.x + position.z*position.z);
	double focalLength = sqrt(c*c + position.y*position.y);
	double ndfl = near_ / focalLength;//zielweite

	cout << "foaclLength: " << focalLength << endl;
	double aspect = width_/(float)height_;
	double widthHalf = near_ * tan(fovy_/2.0);

//	Point vs = position;//richtig?!
//	vs.x *= eyesep_ / 2.0f;
//	vs.y *= eyesep_ / 2.0f;
//	vs.z *= eyesep_ / 2.0f;
//	if (isLeftEye) {
//		vs.x = -vs.x;
//		vs.y = -vs.y;
//		vs.z = -vs.z;
//	}
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	//off-axis
	float left, right, top, bottom;
	if (!isLeftEye) {
		left = -aspect*widthHalf - 0.5f * eyesep_ * ndfl;
		right = aspect*widthHalf - 0.5f * eyesep_ * ndfl;
	} else {
		left = -aspect*widthHalf + 0.5f * eyesep_ * ndfl;
		right = aspect*widthHalf + 0.5f * eyesep_ * ndfl;
	}
	top = widthHalf;
	bottom = - widthHalf;
	cout << "left: " << left << "  right: " << right << endl;

	glFrustum(left, right, top, bottom, near_, far_);


	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
//	gluLookAt(position.x + vs.x, position.y + vs.y, position.z + vs.z,
//			focus.x + vs.x, focus.y +vs.y, focus.z + vs.z,
//			0, 1, 0);
	gluLookAt(camPos[0], camPos[1], camPos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

}

void setRedAanaglyph() {
	//right eye red
	glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);

	setFrustum(false);
	drawGeometry();
}

void setBlueAnaglyph() {
	//left eye blue
	glColorMask(GL_FALSE, GL_FALSE, GL_TRUE , GL_TRUE);

	setFrustum(true);
	drawGeometry();
}

void display() {

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	if (isAnaglyph) {
		//display in red-blue overlay
//		setRedAanaglyph();
		setBlueAnaglyph();
		setRedAanaglyph();

		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

	} else {
		//display in normal mode
		drawGeometry();
	}

	glutSwapBuffers();

}

void reshape(int width, int height) {

}


void setPerspective(int width, int height) {

	width_ = width;
	height_ = height;

	glViewport(0, 0, width_, height_);
	setFrustum(true);
//	glMatrixMode(GL_PROJECTION);
//	glLoadIdentity();
////	gluPerspective(fovy_, width_/float(height_), near_, far_);
//	double l,r,b,t;
//	t = near_ * tan(fovy_ * M_PI / 360.0);
//	b = -t;
//	l = b * width_/float(height_);
//	r = t * width_/float(height_);
//1
//	glFrustum(l, r, b, t, near_, far_);
//
//	glMatrixMode(GL_MODELVIEW);
//	glLoadIdentity();
//	gluLookAt(camPos[0], camPos[1], camPos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void specialkey(int k, int x, int y) {
	if (k == GLUT_KEY_LEFT) {
		angle -= 1.0;
	} else if(k == GLUT_KEY_RIGHT) {
		angle += 1.0;
	}
	glutPostRedisplay();
}


void keyPressed(unsigned char key, int x, int y) {
	switch(key) {
		case 'd':
			isAnaglyph = true;
			glutPostRedisplay();
		break;
		case 'n':
			isAnaglyph = false;
			setPerspective(width_, height_);
			glutPostRedisplay();
		break;
	}
}

void initGL() {
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	setPerspective(width_, height_);

	glShadeModel(GL_SMOOTH);
	glEnable(GL_LIGHTING);
	glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
	glEnable(GL_LIGHT0);
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	position.x = camPos[0];
	position.y = camPos[1];
	position.z = camPos[2];
	focus.x = 0;
	focus.y = 0;
	focus.z = 0;


}

int main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
	glutInitWindowSize(width_, height_);
	glutCreateWindow("Computergrafik I Test");
	initGL();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutSpecialFunc(specialkey);
	glutKeyboardFunc(keyPressed);

	glutMainLoop();
}
